from django.urls import reverse_lazy
from django.views.generic.list import ListView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from braces.views import LoginRequiredMixin, PermissionRequiredMixin
from django.shortcuts import redirect, get_object_or_404
from django.forms.models import modelform_factory
from django.apps import apps
from django.db.models import Count
from django.views.generic.detail import DetailView
from django.views.generic.base import TemplateResponseMixin, View

from courese.models import Subject
from courese.forms import ModuleFormSet
from courese.models import Course, Module, Content
from students.forms import CourseEnrollForm



from braces.views import CsrfExemptMixin, JSONRequestResponseMixin
"""
csrfExemptMixin：用来避免在POST请求中检查一个CSRF token。
JsonRequestResponseMixin：将请求的数据分析为JSON并且将相应
也序列化成JSON并且返回一个application/json内容类型的HTTP
响应。
"""
class CourseListView(TemplateResponseMixin, View):

    model = Course
    template_name = 'courses/course/list.html'

    def get(self, request, subject=None):
        subjects = Subject.objects.annotate(
            #   查询一个课程主题包含多少课程
            total_courses = Count('courses')
        )
        courses = Course.objects.annotate(
            #   查询一个课程包含多少模型
            total_modules = Count('modules')
        )

        if subject:
            subject = get_object_or_404(Subject, slug=subject)
            courses = courses.filter(subject=subject)
        return self.render_to_response(
                        {'subjects': subjects,
                         'subject': subject,
                         'courses': courses
                         }
                    )


class CourseDetailView(DetailView):
    """  课程详情页 """
    model = Course
    template_name = 'courses/course/detail.html'

    def get_context_data(self, **kwargs):
        context = super(CourseDetailView, self).get_context_data(**kwargs)
        context['enroll_form'] = CourseEnrollForm(initial={'course':self.object})
        return context


class ModuleOrderView(CsrfExemptMixin, JSONRequestResponseMixin, View):
    def post(self, request):
        for id, order in self.request_json.items():
            Module.objects.filter(id=id,
                                  course__owner=request.user).update(order=order)
        return self.render_json_response({'saved': 'OK'})


class ContentOrderView(CsrfExemptMixin, JSONRequestResponseMixin, View):
    def post(self, request):
        for id, order in self.request_json.items():
            Content.objects.filter(id=id, module__course__owner=request.user).update(order=order)
        return self.render_json_response({'saved': 'OK'})


class CourseModuleUpdateView(TemplateResponseMixin, View):
    template_name = 'manage/course/module/formset.html'
    course = None

    def get_formset(self, data=None):
        return ModuleFormSet(instance=self.course,data=data)

    def dispatch(self, request, pk):
        self.course = get_object_or_404(Course,id=pk,owner=request.user)
        return super(CourseModuleUpdateView, self).dispatch(request, pk)

    def get(self, request, *args, **kwargs):
        formset = self.get_formset()
        return self.render_to_response({'course': self.course,'formset': formset})

    def post(self, request, *args, **kwargs):
        formset = self.get_formset(data=request.POST)
        if formset.is_valid():
            formset.save()
            return redirect('manage_course_list')
        return self.render_to_response({'course': self.course,'formset': formset})


class ContentCreateUpdateView(TemplateResponseMixin, View):
    module = None
    model = None
    obj = None
    template_name = 'courses/manage/content/form.html'

    def get_model(self, model_name):
        if model_name in ['text', 'video', 'image', 'file']:
            return apps.get_model(app_label='courese', model_name=model_name)
        return None

    def get_form(self, model, *args, **kwargs):
        Form = modelform_factory(model, exclude=[
            'owner', 'order', 'created', 'updated'
        ])

        return Form(*args, **kwargs)

    def dispatch(self, request, module_id, model_name, id=None):
        self.module = get_object_or_404(Module,
                                        id=module_id,
                                        course__owner=request.user)

        self.model = self.get_model(model_name)
        if id:
            self.obj = get_object_or_404(self.model,
                                         id=id,
                                         owner=request.user)
        return super(ContentCreateUpdateView, self).dispatch(request, module_id, model_name, id)

    def get(self, request, module_id, model_name, id=None):
        form = self.get_form(self.model, instance=self.obj)
        return self.render_to_response({'form': form,
                                        'object': self.obj})

    def post(self, request, module_id, model_name, id=None):
        form = self.get_form(self.model,
                             instance=self.obj,
                             data=request.POST,
                             files=request.FILES)
        if form.is_valid():
            obj = form.save(commit=False)
            obj.owner = request.user
            obj.save()
            if not id:
                Content.objects.create(module=self.module,item = obj)
                return redirect('courese:module_content_list', self.module.id)
        return self.render_to_response({'form': form,
                                        'object': self.obj})


class ContentDeleteView(View):
    def post(self, request, id):
        content = get_object_or_404(Content,id=id,module__course__owner=request.user)
        module = content.module
        content.item.delete()
        content.delete()
        return redirect('courese:module_content_list', module.id)


class ModuleContentListView(TemplateResponseMixin, View):
    template_name = 'manage/course/module/content_list.html'

    def get(self, request, module_id):
        module = get_object_or_404(Module, id=module_id, course__owner=request.user)
        return self.render_to_response({'module': module})


class OwnerMixin(object):

    """
    重写了这个视图的get_queryset()
    方法来只对当前用户创建
    的课程进行检索
    """
    def get_queryset(self):
        qs = super(OwnerMixin, self).get_queryset()
        return qs.filter(owner=self.request.user)


class OwnerEditMixin(object):
    def form_valid(self, form):
        form.instance.owner = self.request.user
        return super(OwnerEditMixin, self).form_valid(form)


class OwnerCourseMixin(OwnerMixin):
    model = Course


# class OwnerCourseEditMixin(OwnerCourseMixin, OwnerEditMixin):
#     fields = ['subject', 'title', 'slug', 'overview']
#     success_url = reverse_lazy('manage_course_list')
#     template_name = 'courese/manage/course/form.html'
class OwnerCourseEditMixin(OwnerMixin, LoginRequiredMixin):
    model = Course
    fields = ['subject', 'title', 'slug', 'overview']
    success_url = reverse_lazy('courese:manage_course_list')


class ManageCourseListView(OwnerCourseMixin, ListView):
    template_name = 'manage/course/list.html'


class CourseCreateView(PermissionRequiredMixin, OwnerCourseEditMixin, CreateView):
    permission_required = 'courese.add_course'


class CourseUpdateView(PermissionRequiredMixin, OwnerCourseEditMixin, UpdateView):
    template_name = 'manage/course/form.html'
    permission_required = 'courese.change_course'


class CourseDeleteView(PermissionRequiredMixin, OwnerCourseMixin, DeleteView):
    template_name = 'manage/course/delete.html'
    success_url = reverse_lazy('courese:manage_course_list')
    permission_required = 'courese.delete_cours'
































